﻿using Authority.Doamin;
using Authority.Doamin.IRepository;
using Authority.Doamin.View;
using HelperFromTheSkeleton.EFBaseRepository;
using Microsoft.EntityFrameworkCore;
using System.Linq.Expressions;

namespace Authority.EFRepositoryImpl.EFRepositoryImpl
{
    public class RoleAuthorityRepositoryImpl : EFBaseTreeRepositoryImpl<RoleAuthority>, IRoleAuthorityRepository
    {

        private readonly AuthorityDbContext _authorityDbContext;
        public RoleAuthorityRepositoryImpl(AuthorityDbContext authorityDbContext) : base(authorityDbContext)
        {
            _authorityDbContext = authorityDbContext;
        }

        public async Task<List<RoleView>> FindRoleView(Expression<Func<RoleAuthority, bool>> expression)
        {
            var menuDBSet = _authorityDbContext.MenuAuthority;
            var actionDBSet = _authorityDbContext.ActionAuthority;
            var routingDBSet = _authorityDbContext.RoutingAuthority;
            var roleMenuDBset = _authorityDbContext.RoleAuthorityMenu;
            var roleActionDBset = _authorityDbContext.RoleAuthorityAction;
            var roleRoutingDbset = _authorityDbContext.RoleAuthorityRouting;
            var resultDB = await (from role in _dbSet.Where(expression)
                                  join roleMenu in roleMenuDBset on role.ID equals roleMenu.RoleAuthorityID into roleMenus
                                  from roleMenuDE in roleMenus.DefaultIfEmpty()
                                  join roleAction in roleActionDBset on role.ID equals roleAction.RoleAuthorityID into roleActions
                                  from roleActionDE in roleActions.DefaultIfEmpty()
                                  join roleRouting in roleRoutingDbset on role.ID equals roleRouting.RoleAuthorityID into roleRoutings
                                  from roleRoutingDE in roleRoutings.DefaultIfEmpty()
                                  join menu in menuDBSet on roleMenuDE.MenuAuthorityID equals menu.ID into menus
                                  from menuDE in menus.DefaultIfEmpty()
                                  join action in actionDBSet on roleActionDE.ActionAuthorityID equals action.ID into actions
                                  from actionDE in actions.DefaultIfEmpty()
                                  join routing in routingDBSet on roleRoutingDE.RoutingAuthorityID equals routing.ID into routings
                                  from routingDE in routings.DefaultIfEmpty()
                                  select new
                                  {
                                      role.ID,
                                      role.Name,
                                      role.Code,
                                      role.ParentID,
                                      role.DateUpTime,
                                      role.DateAddTime,
                                      role.IsDelete,
                                      MenuID = menuDE == null?null: (Guid?)menuDE.ID,
                                      MenuName = menuDE == null ? null : menuDE.Name,
                                      MenuCode = menuDE == null ? null : menuDE.Code,
                                      ActionID = actionDE == null ? null : (Guid?)actionDE.ID,
                                      ActionName = actionDE == null ? null : actionDE.Name,
                                      ActionCode = actionDE == null ? null : actionDE.Code,
                                      RoutingID = routingDE ==  null?null:(Guid?)routingDE.ID,
                                      RoutingName = routingDE == null ? null : routingDE.Name,
                                      RoutingCode = routingDE == null ? null : routingDE.Code,
                                  }).ToListAsync();
            var resultGroupByRoleID = resultDB.GroupBy(m => m.ID).ToList();
            var result = new List<RoleView>();
            foreach (var val in resultGroupByRoleID)
            {
                var role = val.FirstOrDefault();
                if (role == null) continue;
                RoleView roleView = new RoleView
                {
                    ID = role.ID,
                    Code = role.Code,
                    IsDelete = role.IsDelete,
                    DateAddTime = role.DateAddTime,
                    DateUpTime = role.DateUpTime,
                    Name = role.Name,
                    ParentID = role.ParentID,
                    ActionInfo = val.Where(m=>m.ActionID!=null).GroupBy(m => m.ActionID??Guid.Empty).ToDictionary(m => m.Key, m => m.FirstOrDefault()?.ActionName ?? ""),
                    MenuInfo = val.Where(m => m.MenuID != null).GroupBy(m => m.MenuID??Guid.Empty).ToDictionary(m => m.Key, m => m.FirstOrDefault()?.MenuName ?? ""),
                    RoutingInfo = val.Where(m => m.RoutingID != null).GroupBy(m => m.RoutingID ?? Guid.Empty).ToDictionary(m => m.Key, m => m.FirstOrDefault()?.RoutingName ?? "")
                };
                result.Add(roleView);
            }
            return result;
        }

    }
}
